/*
 * Driver_Serial.c
 *
 *  Created on: Nov 23, 2024
 *      Author: 60146
 */

#include "Driver_Serial.h"
#include "main.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "Driver_OLED.h"
#include "stdarg.h"
#include "usart.h"


/* Includes -------------------------------------------------------------------*/

/* define ---------------------------------------------------------------------*/
#define TJC_LOG_BUFFER_SIZE		512
/* typedef --------------------------------------------------------------------*/

/* variables ------------------------------------------------------------------*/
static uint8_t uart1_rec_buf[1024];
static uint8_t uart2_rec_buf[1024];
/* Private function prototypes ------------------------------------------------*/
static void SerialReceivedHandle(uint16_t Size);
static void UART1_CMD_Handler(uint8_t *buf,uint16_t Size);
static void UART2_CMD_Handler(uint8_t *buf,uint16_t Size);
void log_tjc(uint8_t *des, uint8_t *str, uint16_t size);

/*
 * 在GCC中重定向printf，要对__io_putchar进行重写，类似于ARMCC中重写fputc
 */
int __io_putchar(int ch)
{
	HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1,100);
	return ch;
}


/**
 * @brief 为了使用非阻塞式发送，新增一个PRINTF函数
 * @param  fmt         My Param doc
 * @param  ...         My Param doc
 * @date 2024-12-14
 * @author 2bam 
 */
void PRINTF(const char *fmt, ...)
{
    va_list args;
    size_t length;
    static char print_buf[1024];

    va_start(args, fmt);
    /* the return value of vsnprintf is the number of bytes that would be
     * written to buffer had if the size of the buffer been sufficiently
     * large excluding the terminating null byte. If the output string
     * would be larger than the rt_log_buf, we have to adjust the output
     * length. */
    length = vsnprintf(print_buf, sizeof(print_buf) - 1, fmt, args);
    if (length > sizeof(print_buf) - 1)
        length = sizeof(print_buf) - 1;

    /* 使用USART1进行输出 2024-12-14 Saturday 01:00:34 */  
    HAL_UART_Transmit_DMA(&huart1,(uint8_t *)print_buf,length);
	HAL_Delay(1);
    va_end(args);
}


/**
 * @brief 重写串口DMA接收不定长数据的回调函数
 * @param  huart       My Param doc
 * @param  Size  	接收到的字节数
 * @date 2024-11-27
 * @author 2bam 
 */
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	if(huart == &huart1)
	{
		HAL_UART_Transmit_DMA(&huart1,uart1_rec_buf,Size);
		UART1_CMD_Handler(uart1_rec_buf,Size);	
	}

	if(huart == &huart2)
	{
		HAL_UART_Transmit_DMA(&huart1,uart2_rec_buf,Size);
		UART2_CMD_Handler(uart2_rec_buf,Size);
	}

	/** 再次启动接收 2024-11-27 Wednesday 23:43:10 */
	StartSerialMonitor();
}

/**
 * @brief 
 * @param  buf         My Param doc
 * @param  Size        My Param doc
 * @date 2024-12-13
 * @author 2bam 
 */
static void UART1_CMD_Handler(uint8_t *buf,uint16_t Size)
{
	log_tjc(NULL,buf,Size);
}


/**
 * @brief 
 * @param  buf         My Param doc
 * @param  Size        My Param doc
 * @date 2024-12-13
 * @author 2bam 
 */
static void UART2_CMD_Handler(uint8_t *buf,uint16_t Size)
{

}


/**
 * @brief 启动串口DMA接收不定长数据
 * @date 2024-11-27
 * @author 2bam 
 */
void StartSerialMonitor(void)
{
	extern  DMA_HandleTypeDef hdma_usart1_rx;
	HAL_UARTEx_ReceiveToIdle_DMA(&huart1,uart1_rec_buf,sizeof(uart1_rec_buf));
	/** 关闭DMA传输过半中断，每次开启时都要关闭 2024-11-27 Wednesday 23:40:02 */
	__HAL_DMA_DISABLE_IT(&hdma_usart1_rx,DMA_IT_HT);

	/** 新增UART2配置 2024-12-13 Friday 22:21:37 */
	extern  DMA_HandleTypeDef hdma_usart2_rx;
	HAL_UARTEx_ReceiveToIdle_DMA(&huart2,uart2_rec_buf,sizeof(uart2_rec_buf));
	/** 关闭DMA传输过半中断，每次开启时都要关闭 2024-11-27 Wednesday 23:40:02 */
	__HAL_DMA_DISABLE_IT(&hdma_usart2_rx,DMA_IT_HT);
}


 __attribute__((unused)) static void SerialReceivedHandle(uint16_t Size)
{
	uint8_t rec[] = {"set pix:(000,00)"};
	char row_x[3] = {0};
	char column_y[2] = {0};
	uint8_t x=0,y=0;
	if(strnicmp((char *)rec,(char *)uart1_rec_buf,8)==0)
	{
		memcpy(row_x,uart1_rec_buf+9,3);
		memcpy(column_y,uart1_rec_buf+13,2);
		x = atoi(row_x);
		y = atoi(column_y);
		printf("command set pix:(%d,%d)\n",x,y);
		OLED_SetPixel(x,y,OLED_COLOR_NORMAL);
		OLED_ShowFrame();
	}
	else
	{
		printf("command wrong!\n");
	}
	/** 清空缓存 */
	//memset(uart1_rec_buf, 0, Size);
}



/**
 * @brief 仿照rt_kprintf制作一个专门用于打印到TJC串口屏的格式化函数
 * @param  fmt         My Param doc
 * @param  ...         My Param doc
 * @date 2024-05-15
 * @author 2bam 
 */
void printf_tjc(const char *fmt, ...)
{
    va_list args;
    size_t length;
    static char rt_log_buf[TJC_LOG_BUFFER_SIZE];

    va_start(args, fmt);
    /* the return value of vsnprintf is the number of bytes that would be
     * written to buffer had if the size of the buffer been sufficiently
     * large excluding the terminating null byte. If the output string
     * would be larger than the rt_log_buf, we have to adjust the output
     * length. */
    length = vsnprintf(rt_log_buf, sizeof(rt_log_buf) - 1, fmt, args);
    if (length > TJC_LOG_BUFFER_SIZE - 1)
        length = TJC_LOG_BUFFER_SIZE - 1;

    /* 使用USART2进行输出 2024/05/15 Wednesday 23:24:28 */  
    HAL_UART_Transmit_DMA(&huart2,(uint8_t *)rt_log_buf,length);
    va_end(args);
}

/**
 * @brief 
 * @param  des         My Param doc
 * @param  str         My Param doc
 * @param  size        My Param doc
 * @date 2024-12-14
 * @author 2bam 
 */
void log_tjc(uint8_t *des, uint8_t *str, uint16_t size)
{
	/** 打印到特定页面 2024-12-14 Saturday 00:25:58 */
	/** 将显示信息修改为追加模式：+= 2024-12-14 Saturday 10:44:40 */
    char buf[TJC_LOG_BUFFER_SIZE] = "serial2.t2.txt+=\"";
	strncat(buf,(char *)str,size);
    strcat(buf,"\"\xff\xff\xff");
    printf_tjc("%s",buf);
}

